<?php

class NCore_Pipe
{
	private $name;	
	private $selectedView = NULL;
	private $views = array();
	private $dataset;
	private $rendered = FALSE;
	private $requiredPortGroup = NULL;
	private $viewSelectedWhenPortGroupUnset = NULL;
	private $requiredPipes = array();
    private $nestedPipe = NULL;
    private $isNestedPipe = false;
	
	function __construct($name)
	{
		$this->withName($name);
        $this->setupViews();
	}
	public function withName($name)
	{
		if(!preg_match(N::REGEX_KEY, $name))
		{
			throw new Exception('Pipe names must begin with a letter; contain letters, numbers, or the underscore; and be no longer than 30 characters.');
		}

		$this->name = $name;
		return $this;
	}
	public function getName()
	{
		return $this->name;
	}
    public function setupViews()
    {
        $this->addView('feedback');
        $this->addView('error');
        $this->addView('default');
        $this->addView('empty');
        $this->addView('blank');
    }
	public function withRendered($bool)
	{
		$this->rendered = $bool;
		return $this;
	}
	public function getRendered()
	{
		return $this->rendered;
	}
	public function addView($view)
	{
		if($view instanceof NCore_View)
		{
			return $this->views[$view->getName()] = $view;
		}
		else
		{
            $v = new NCore_View($view);

            switch($view)
            {
                case 'feedback':
                    $v->withMappings(array('message'=>'{message}'));
                    $v->withMarkup(<<< FEEDBACK
<p>Some data is invalid:</p>
<ul class="status_warning">
<!--data-->
<li>{message}</li>
<!--data-->
</ul>

FEEDBACK
                    );
                    break;

                case 'error':
                    $v->withMarkup(<<< ERROR
<p class="status_warning">We experienced an error.
<br />We could not render this section of the page.</p>

ERROR
                    );
                    break;

                case 'default':
                    $v->withMarkup(<<< DEFAULT
<p>We could not find any markup for the default view.</p>

DEFAULT
                    );
                    break;

                case 'empty':
                    $v->withMarkup(<<< EMPTY
<p>Currently, there are no results.</p>

EMPTY
                    );
                    break;

                case 'blank':
                    $v->withMarkup('');
                    break;

                case 'a':
                    $v->withMarkup(<<< DEFAULT
<p>We could not find any markup for the 'a' view.</p>

DEFAULT
                    );
                    break;

                case 'b':
                    $v->withMarkup(<<< DEFAULT
<p>We could not find any markup for the 'b' view.</p>

DEFAULT
                    );
                    break;
            }

            return $this->views[$view] = $v;
		}
	}
	public function withDataset(NCore_Dataset $dataset)
	{
		$this->dataset = $dataset;
		return $this;
	}
	public function getDataset()
	{
		return $this->dataset;
	}
	public function withSelectedView($name)
	{
		$this->selectedView = $name;
		return $this;
	}
	public function getSelectedView()
	{
		return $this->selectedView;
	}
	public function getView($name = NULL)
	{
		if(!is_null($name))
			return $this->views[$name];
	
		return $this->views[$this->selectedView];
	}
	// delegate methods for default view
	public function withMappings($arr)
	{
		$this->getView('default')->withMappings($arr);
		return $this;
	}
	public function getMappings()
	{
		return $this->getView('default')->getMappings();
	}
	public function addWhitelist($key, $arr)
	{
		$this->getView('default')->addWhitelist($key, $arr);
		return $this;
	}
	public function getWhitelists()
	{
		return $this->getView('default')->getWhitelists();
	}
	public function withMarkup($markup)
	{
		$this->getView('default')->withMarkup($markup);
		return $this;
	}
	public function getMarkup()
	{
		return $this->getView('default')->getMarkup();
	}	
	public function withErrorMarkup($markup)
	{
		$this->getView('error')->withMarkup($markup);
		return $this;
	}
	public function getErrorMarkup()
	{
		return $this->getView('error')->getMarkup();
	}	
	public function withFeedbackMarkup($markup)
	{
		$this->getView('feedback')->withMarkup($markup);
		return $this;
	}
	public function getFeedbackMarkup()
	{
		return $this->getView('feedback')->getMarkup();
	}	
	public function withEmptyMarkup($markup)
	{
		$this->getView('empty')->withMarkup($markup);
		return $this;
	}
	public function getEmptyMarkup()
	{
		return $this->getView('empty')->getMarkup();
	}	
	public function withRequiredPortGroup($pg, $viewSelectedWhenPortGroupUnset = 'error')
	{
		$this->viewSelectedWhenPortGroupUnset = $viewSelectedWhenPortGroupUnset;
		$this->requiredPortGroup = $pg;
		return $this;
	}
	public function getRequiredPortGroup()
	{
		return $this->requiredPortGroup;
	}	
	public function getViewSelectedWhenPortGroupUnset()
	{
		return $this->viewSelectedWhenPortGroupUnset;
	}
	public function withRequiredPipes($pipeNamesArray)
	{
		if(!is_array($pipeNamesArray)){throw new Exception('The withRequiredPipes() method on the pipe \''.$this->getName().'\' only accepts an array of pipe names.');}
		$this->requiredPipes = $pipeNamesArray;
		return $this;
	}

    public function withNestedPipe($pipeName)
    {
        $this->nestedPipe = $pipeName;
        return $this;
    }

    public function getNestedPipe()
    {
        return $this->nestedPipe;
    }

    public function isNestedPipe($bool = NULL)
    {
        if (is_null($bool))
        {
            return $this->isNestedPipe;
        }
        else
        {
            if (!is_bool($bool))
                throw new Exception('isNestedPipe() only accepts boolean values.');

            $this->isNestedPipe = $bool;
            return $this;
        }
    }

	public function getRequiredPipes()
	{
		return $this->requiredPipes;
	}
	public function addDatabindingMethod($obj, $method)
	{
		$this->getView('default')->addDatabindingMethod($obj, $method);
		return $this;
	}
	public function getDatabindingMethods()
	{
		return $this->getView('default')->getDatabindingMethods();
	}	
	public function addDataboundMethod($obj, $method)
	{
		$this->getView('default')->addDataboundMethod($obj, $method);
		return $this;
	}
	public function getDataboundMethods()
	{
		return $this->getView('default')->getDataboundMethods();
	}
	public function addRowDatabindingMethod($obj, $method)
	{
		$this->getView('default')->addRowDatabindingMethod($obj, $method);
		return $this;
	}
	public function getRowDatabindingMethods()
	{
		return $this->getView('default')->getRowDatabindingMethods();
	}
	public function addRowDataboundMethod($obj, $method)
	{
		$this->getView('default')->addRowDataboundMethod($obj, $method);
		return $this;
	}
	public function getRowDataboundMethods()
	{
		return $this->getView('default')->getRowDataboundMethods();
	}	
	
	public function fill($data)
	{
		if($data instanceof NCore_IDatasource)
		{
			$this->withDataset($data->getDataset());
		}
		elseif($data instanceof NCore_Dataset)
		{
			$this->withDataset($data);
		}
		else
		{
			throw new Exception('The fill method on the pipe \''.$this->getName().'\' only accepts arguments of types NCore_Dataset or NCore_IDatasource.');
		}
		if(count($this->dataset) > 0)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	function __call($method, $args)
	{
		throw new Exception('There is no method called \''.$method.'\'() on the pipe \''.$this->getName().'.');
	}
}

?>